/*************************************************************************
	Animation Layer

*************************************************************************/

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;

[Serializable]
public class UTVPAnimationLayer_SaveData : UTVPLayer_SaveData
{
	public UTVPAnimationLayer_SaveData() {}
		
	public string CurrAnimSequenceName = null;
	public bool AnimPause = true;
	public int CurrFrameIdx = 0;
	public float AnimTimer = 0.0f;
}

[Serializable]
public class UTVPAnimFrameInfo : IComparable<UTVPAnimFrameInfo>
{
	public string name;
	public int x, y, w, h;
	public int sliceLeft, sliceRight, sliceTop, sliceBottom;
	public int trimLeft, trimRight, trimTop, trimBottom;
	
	public int CompareTo (UTVPAnimFrameInfo other)
	{
		return name.CompareTo(other.name);
	}
}

[Serializable]
public class UTVPAnimSequenceInfo : IComparable<UTVPAnimSequenceInfo>
{
	public string name;
	[System.NonSerialized]
	public List<Texture2D> frameListForEditor = new List<Texture2D>(); // for Editor Only
	public string[] frames;
	public int interval = 50;
	public bool loop = true;
	
	public int CompareTo (UTVPAnimSequenceInfo other)
	{
		return name.CompareTo(other.name);
	}
}

//[RequireComponent(typeof(MeshCollider))]
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class UTVPAnimationLayer : UTVPLayer {

	// Animation
	public bool AnimPause = true;
	protected string m_CurrAnimSequenceName = null;
	private UTVPAnimSequenceInfo m_CurrAnimSequence = null;
	public UTVPAnimSequenceInfo CurrAnimSequence { get { return m_CurrAnimSequence; } }
	protected int m_CurrFrameIdx = 0;
	private UTVPAnimFrameInfo m_CurrFrameInfo = null;
	public UTVPAnimFrameInfo CurrFrame { get { return m_CurrFrameInfo; } }
	private float m_AnimTimer = 0.0f;
	
	public override UTVPImage Image
	{
		get { return m_Image; }
		set
		{
			if ( m_Image == value)
				return;

			m_CurrAnimSequenceName = null;
			m_CurrAnimSequence = null;
			m_CurrFrameInfo = null;
			m_CurrFrameIdx = -1;
			
			base.Image = value;
		}
	}
	
	public void SetAnimOption(string animName, bool animPause, int currFrameIdx, bool resize)
	{
		CurrAnimSequenceName = animName;
		this.AnimPause = animPause;
		
		if (m_CurrAnimSequence == null)
			return;
		if (m_CurrAnimSequence.frames.Length <= 1)
			this.AnimPause = true;
		
		SetCurrFrameIdx_impl(currFrameIdx, resize);
	}
	
	public string CurrAnimSequenceName
	{
		get { return m_CurrAnimSequenceName; }
		set
		{
			if (Image == null || Image.frameDic == null || m_CurrAnimSequenceName == value)
				return;
			
			m_CurrAnimSequenceName = value;
			if (m_CurrAnimSequenceName != null)
				m_CurrAnimSequence = Image.sequenceDic[m_CurrAnimSequenceName];
			else
				m_CurrAnimSequence = null;
			
			m_CurrFrameInfo = null;
			m_CurrFrameIdx = -1;
		}
	}
	
	public int CurrFrameIdx
	{
		get { return m_CurrFrameIdx; }
		set
		{
			SetCurrFrameIdx_impl(value, false);
		}
	}
	
	private void SetCurrFrameIdx_impl(int idx, bool resize)
	{
		if (m_CurrAnimSequence == null)
			return;
					
		m_CurrFrameIdx = idx;
		
		if (m_CurrFrameIdx >=0 && m_CurrFrameIdx < m_CurrAnimSequence.frames.Length)
		{
			m_CurrFrameInfo = Image.frameDic[m_CurrAnimSequence.frames[m_CurrFrameIdx]];
				
			m_TrimLeft = m_CurrFrameInfo.trimLeft;
			m_TrimTop = m_CurrFrameInfo.trimTop;
			m_TrimRight = m_CurrFrameInfo.trimRight;
			m_TrimBottom = m_CurrFrameInfo.trimBottom;
			SetImagePos(m_CurrFrameInfo.x, m_CurrFrameInfo.y);
			SetImageSize(m_CurrFrameInfo.w, m_CurrFrameInfo.h,
				m_CurrFrameInfo.sliceLeft, m_CurrFrameInfo.sliceTop, m_CurrFrameInfo.sliceRight, m_CurrFrameInfo.sliceBottom);
			if (resize)
				SetSize(m_CurrFrameInfo.w, m_CurrFrameInfo.h);
		}
		else
			m_CurrFrameInfo = null;
			
		m_AnimTimer = Time.time + m_CurrAnimSequence.interval / 1000.0f;
		RefreshPosAndSize();
	}
	
	public void StartAnimation(string animName, int currFrameIdx, bool animPause)
	{
		SetAnimOption(animName, animPause, currFrameIdx, false);
	}
	
	// Use this for initialization
	protected override void Awake () {
		base.Awake();
		m_CurrAnimSequenceName = null;
		m_CurrAnimSequence = null;
		m_CurrFrameInfo = null;
		m_CurrFrameIdx = -1;
	}
	
	// Update is called once per frame
	protected internal override void LayerUpdate ()
	{
		if (Image.frameDic != null && !AnimPause && m_CurrAnimSequence != null && m_CurrAnimSequence.frames.Length > 1)
		{
			float currTime = Time.time;
			
			if (currTime > m_AnimTimer)
			{
				if (CurrFrameIdx >= m_CurrAnimSequence.frames.Length)
				{
					if (m_CurrAnimSequence.loop)
					{
						CurrFrameIdx = 0;
						while (currTime > m_AnimTimer)
							m_AnimTimer += m_CurrAnimSequence.interval / 1000.0f;
					}
					else
					{
						AnimPause = true;
						OnAnimationCompleted();
					}
				}
				else
				{
					CurrFrameIdx++;
					while (currTime > m_AnimTimer)
						m_AnimTimer += m_CurrAnimSequence.interval / 1000.0f;
				}
			}
		}

		base.LayerUpdate();
	}
	
	protected virtual void OnAnimationCompleted() {}
	
	protected override void AssignSelf(UTVPLayer src)
	{
		base.AssignSelf(src);
		if (src is UTVPAnimationLayer)
		{
			UTVPAnimationLayer srcTemp = (UTVPAnimationLayer)src;
			CurrAnimSequenceName = srcTemp.CurrAnimSequenceName;
			AnimPause = srcTemp.AnimPause;
			m_AnimTimer = srcTemp.m_AnimTimer;
			SetCurrFrameIdx_impl(srcTemp.CurrFrameIdx, false);
		}
	}
	
	protected override UTVPLayer_SaveData CreateSaveDataBuff()
	{
		return new UTVPAnimationLayer_SaveData();
	}
	
	protected override void GetSelfData(UTVPLayer_SaveData dataBuff)
	{
		base.GetSelfData(dataBuff);
		
		UTVPAnimationLayer_SaveData dataBuffSelf = (UTVPAnimationLayer_SaveData)dataBuff;
		dataBuffSelf.CurrAnimSequenceName = CurrAnimSequenceName;
		dataBuffSelf.AnimPause = AnimPause;
		dataBuffSelf.AnimTimer = m_AnimTimer;
		dataBuffSelf.CurrFrameIdx = CurrFrameIdx;
	}
	
	protected override void SetSelfData(UTVPLayer_SaveData dataBuff)
	{
		base.SetSelfData(dataBuff);

		UTVPAnimationLayer_SaveData dataBuffSelf = (UTVPAnimationLayer_SaveData)dataBuff;
		CurrAnimSequenceName = dataBuffSelf.CurrAnimSequenceName;
		AnimPause = dataBuffSelf.AnimPause;
		m_AnimTimer = dataBuffSelf.AnimTimer;
		SetCurrFrameIdx_impl(dataBuffSelf.CurrFrameIdx, false);
	}
}
